// //////////////////////////////////////////////////////////
// tests.cpp
// Copyright (c) 2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//

// simple test suite for hash-library
// g++ tests.cpp ../crc32.cpp ../md5.cpp ../sha1.cpp ../sha256.cpp ../sha3.cpp -o tests && ./tests

#include "../crc32.h"
#include "../md5.h"
#include "../sha1.h"
#include "../sha256.h"
#include "../sha3.h"
#include "../keccak.h"

#include "../hmac.h"

#include <string>
#include <vector>

#include <iostream>


struct TestSet
{
  const char* input;
  const char* crc32b;
  const char* md5;
  const char* sha1;
  const char* sha256;
  const char* sha3_256;
};

const size_t NumTests = 100;
TestSet testset[NumTests] =
{ // generated by PHP script, SHA3 vectors from https://raw.githubusercontent.com/gvanas/KeccakCodePackage/master/TestVectors/ShortMsgKAT_SHA3-256.txt
  /*
    $lines = file("ShortMsgKAT_SHA3-256.txt");
    for ($i = 1; $i <= 100; $i++)
    {
      $hex  = trim(strtolower(substr($lines[8 * 4 * $i + 3], 6)));
      $sha3 = trim(strtolower(substr($lines[8 * 4 * $i + 4], 5)));

      $msg = hex2bin($hex);
      echo "{ \"$hex\", \"".
           hash("crc32b", $msg).'", "'.
           hash("md5",    $msg).'", "'.
           hash("sha1",   $msg).'", "'.
           hash("sha256", $msg).'", "'.
           "$sha3\" }, // $i\n";
    }
  */

  { "cc", "40d06116", "a2e970f170961ce879190d64982c94ec", "a6f57425137e9aa54537f0b3f5364ce165aedb0a", "1dd8312636f6a0bf3d21fa2855e63072507453e93a5ced4301b364e91c9d87d6", "677035391cd3701293d385f037ba32796252bb7ce180b00b582dd9b20aaad7f0" }, // 1
  { "41fb", "82d4472f", "70d3e9af7232e67b6b6f3e71f7399438", "a6a5d330d9928b452ca7e34e946c52ea4f6eaa15", "0f8fa28112230a7a0b3cabcb64d37bd38f5023b1391e38f89a9b29f32b0aefbc", "39f31b6e653dfcd9caed2602fd87f61b6254f581312fb6eeec4d7148fa2e72aa" }, // 2
  { "1f877c", "c54a0ec4", "f7ac37ba79246d6a36b49c0993791110", "d17212f7dbfa31d10b68d480bc91cd3e1596be86", "ab0213910396c8d94cbf3b6c97de1fc97fc55cea4b6b6cc25ea4b71e7e7bc28c", "bc22345e4bd3f792a341cf18ac0789f1c9c966712a501b19d1b6632ccd408ec5" }, // 3
  { "c1ecfdfc", "5a545e7c", "af9116916ca42299e557e55cfa3e1591", "dc148b935ff1614ba17bdbad6e5392179e412f0d", "7df4925396138971f4a733680107ce202c5c5991dbc8737ad07eb4da85a06f85", "c5859be82560cc8789133f7c834a6ee628e351e504e601e8059a0667ff62c124" }, // 4
  { "21f134ac57", "d086fa95", "29057856dd5548ac8c1cca4b27489449", "404be2d420abc459707149bb79c8065aded00e7e", "a0ba0190c23bf1140cf5bf5a07e1140df55389792283bb6a8b5867a539ac7931", "55bd9224af4eed0d121149e37ff4d7dd5be24bd9fbe56e0171e87db7a6f4e06d" }, // 5
  { "c6f50bb74e29", "cdff1654", "d175ad6887766bf159f1bde8e514465a", "6685c62b13f7fc0703fd246c050a19cce98fcd97", "e2c0a1c005c4aa91ad89e509b603c5c0f474a18df291e5ca378725a9ad76fb09", "ae0cbc757d4ab088e172abfd8746289950f92d38a25295658dbf744b5635af04" }, // 6
  { "119713cc83eeef", "54465641", "27e281ab44bce27391bc7cee7b0f3437", "1fcd96a8c76f4d884c744bf840507acfe646ff76", "96e043b747fa1737d63d83b898987d3e70c816175a50333077ce4e7602255975", "e340c9a44373efcc212f3cb66a047ac34c87ff1c58c4a14b16a2bfc34698bb1d" }, // 7
  { "4a4f202484512526", "696ab8df", "90ea55f66c4b5239df52b05349455037", "928a171eacc5698811ef2992712458a9fa043955", "1b1c9bf7e050805714c81c03a05a6961e924bbaca37cb5b9998cb46bb2be4fa5", "ba4fb009d57a5ceb85fc64d54e5c55a55854b41cc47ad15294bc41f32165dfba" }, // 8
  { "1f66ab4185ed9b6375", "c0b622ae", "164a8c44008d14028fae0cf7b9d566aa", "8b81a9a58e987edb923fe6118ca6099cb71ad55a", "0eb3c0f5f345bd6cf98cf870886abc1817a0c5dde08d62f870a6b4a006979ee3", "b9886ef905c8bdd272eda8298865e0769869f1c964460d1aa9d7a0c687707ccd" }, // 9
  { "eed7422227613b6f53c9", "2029782c", "e57498c9318a515fcd8980dc319aa10a", "261830dfe450e4d58e5315cb0cb9d31c725cc406", "9758c2ee9d9782c6a3e60b394b16837689ab6f13c4157d45fc6ee7597a59448f", "fab8f88d3191e21a725b21c63a02cad3fa7c450ef8584b94cfa382f393422455" }, // 10
  { "eaeed5cdffd89dece455f1", "42fcfb29", "5e49b16a26a63aef2912956918f6a919", "c0507f76cea3e4d46edf256d49fe0ccf0ec2145a", "0a5f39f0e909a63bc93a76a21e94d62a0451d9f8123ecc5a59e5bd240b2850b0", "9363acd3f48bb91a8998aa0e8df75c971770a16a71e7d2334409734cd7d0a9ee" }, // 11
  { "5be43c90f22902e4fe8ed2d3", "4fbb1441", "e907bfc096655d56d3799b422f0ddd16", "f089f569228795551af51bbff935ac0e6b625c78", "c6057a042954e08be906ff710b042dbf6352f8b958b8ade708439063710bb5e2", "16932f6f65deaad5780e25ab410c66b0e4198eba9f4ed1a25ee24f7879faefe2" }, // 12
  { "a746273228122f381c3b46e4f1", "ad022e12", "ae0549cbb3704b5d2d1f18dbbc159de4", "2b269ce05fc8392c0333f8d1aec8ce32ed969e32", "7c48389c069dedf88be6534d34dfc20c109ce40788b96ddebc1e9209c0ca49de", "1c28100e0ef50671c7ea3e024fa3ba9da2ebddb4de264c3a2426c36ad3f91c61" }, // 13
  { "3c5871cd619c69a63b540eb5a625", "1ca57d8b", "c4d0ef66c3ddc1f3ee998de21e6834ec", "88b2b64f3ada91ed6cd29e80b8c67e2cd6ff555a", "82af41b707f8336fadc9fdbfc00b50d11a27b46e1e022ed4865896dca259377d", "8183be4875fab7ec5f99ed94f5f900cf1d6b953d8f71e1e7cc008687980e613a" }, // 14
  { "fa22874bcc068879e8ef11a69f0722", "0e69af1c", "3af22d0558d6cb039e164bb47bc48265", "46234cafafbce55281c87102559f47450976bb08", "f479cdfa3488c4d8e44c8e10167a54cbc1142a7a75bb5a0ee6aa647a93a65d0f", "3b1a6d21fe44691dac4eb7c593a6d8523cb606e63cf00e94d711a574248daca5" }, // 15
  { "52a608ab21ccdd8a4457a57ede782176", "1ccb278f", "72d4071b78731c61b61076067f3ef40b", "2d64a7c42ce0cb8dae2617effd031b5fe328eef6", "7ae441ed62ba0263f194386043ac4ba452bc593a5a9ad001da5c70ddc533abb1", "2c7e7cb356fdc68ec8927e499d2a6bae2b781817919c829ebbe8225baed46967" }, // 16
  { "82e192e4043ddcd12ecf52969d0f807eed", "4e448a12", "e880a1c8344c01c1aede282f4a0c6930", "f4c49546bb55bfadddb0e8f0c14add76039250ce", "b06558895e83f861bcdc2556f7e6377468341b352745caf2605df544275e9949", "c7b12eff692d842110cc39ac60616707acb3f9b0f1cb361b94577efc529ca26c" }, // 17
  { "75683dcb556140c522543bb6e9098b21a21e", "4b50b9e1", "9b92909591db3d4957047c6bb3c06880", "bb479acce571cec0775532af7c7b19c2a719456d", "7da11d5a5c7e39d51d7509bd8f5819f7110a3f7aecaf314cf7d6a5943e70ac66", "493ebaebc04776f4e067555afa09b58c850fdf1b0e22d4bf006ce41c091dc762" }, // 18
  { "06e4efe45035e61faaf4287b4d8d1f12ca97e5", "45cad288", "b1f1c44c82ba049a4f540e0206cdd045", "82c2585cbecc9ade3bd64895a84a85bb97952e43", "0b9e07de6287032320423371a8ee66e149ae208e248587443e122c9f8cc600fb", "1d01f3120ecfbdd28dce44317666cf864f52391b9eca3843db45667c2e0a98ad" }, // 19
  { "e26193989d06568fe688e75540aea06747d9f851", "1a5edc0e", "9e0e0f99c95fa883fc65e74bc94149e5", "bdfd2785148f71a6ac5790d3e65cb7638a3efdc6", "e88d019b09a378a39bd5bfa33215c358303c7f13004ce3a12650aa70d01b8ca0", "2c1e61e5d45203f27b86f1293a80bab34192daf42b8623b12005b2fb1c18acb1" }, // 20
  { "d8dc8fdefbdce9d44e4cbafe78447bae3b5436102a", "2803f7c6", "2c6e363d11a7a5d810dce54d3e28c409", "3ac65fbaceb1591da5b96bfa50c825e7e7c61a20", "fdfa03e288a4af6d325049bfc4b76e9c8178321d484ae88fb1025d26bef78679", "ad0e3f29767067e929d1cecd95582df8f2a9beb92eaa27eeb315f620365a9244" }, // 21
  { "57085fd7e14216ab102d8317b0cb338a786d5fc32d8f", "64ba010b", "92ca1e70af2d4926eaca1acb0a7204da", "88ba72d3f7331c8235bfac25f0af1fce30534676", "a05e71cd70727ee68b029f36bdd7838dc3c69bbdb956c21b68dfa439421af5f9", "2b4eb5de20e86074cabb55bfa63a5c8c6ae15679302061845b9cf233e17c906b" }, // 22
  { "a05404df5dbb57697e2c16fa29defac8ab3560d6126fa0", "53948692", "1ca08b8e52e2d6956504aeeb4175d98c", "1c3329ab472a203c11a74936c786177462822bd8", "7ea63cd84b9f0b9ce4daf224835d06e029a4601eeb5a37496799a3d84ed42f8d", "6ae04c6c6f3651f1f64c0ad69733990b41747c93f87acb813bb25bb1fc0eff07" }, // 23
  { "aecbb02759f7433d6fcb06963c74061cd83b5b3ffa6f13c6", "5e55297b", "f9715ac28f13a90a4dfb017aee4dd9b1", "76538ebb720710421b935ce23fbe37543e090cb6", "19045e899afc4a35967ca5c7970a5b0ddc99f70f69716dcf62c46825be0aa457", "40f9f55bc55da466bc3dc1f89835a64094572de73d64ed6646a1d3b667be70a9" }, // 24
  { "aafdc9243d3d4a096558a360cc27c8d862f0be73db5e88aa55", "f7f32407", "6d71d851e6fc1cc3a44be9c16e546cb9", "e294d8908f122b8d7ccfc1223058636eb276d405", "4c8487b6a2561455e1535c1462722c1042fe2f478ead5a6f65f39bad004cab59", "c64becf7b75fc885d5853924f2b7d37abcefd3da126bb817697e1a09152b1ebe" }, // 25
  { "7bc84867f6f9e9fdc3e1046cae3a52c77ed485860ee260e30b15", "edbb117c", "8a104d5ba0f66e66042486f7e106fe87", "a1a306755332086effbf26d6c20af9b50e415285", "8c41fa0b07f82b9cd0026de7e38059680f69f2d20f426596e88b4d800aa638b2", "57d46a6bc8fab33601538dad27f98c66443032cc3912434c28eb88d0af44c52c" }, // 26
  { "fac523575a99ec48279a7a459e98ff901918a475034327efb55843", "39f0e9db", "7de1128f904f39f92f1c51989c94aaf8", "a58b983e90870a964296a164bd02b62ffff7e12f", "a84dbb8acfe2c5ab82c2ed371040a3221f7cde534baf134e24534a3b5105da69", "7c956503d5b4dbb764ff8e66fa74ce0f9132da90ea3543f669c9dd08e413e33c" }, // 27
  { "0f8b2d8fcfd9d68cffc17ccfb117709b53d26462a3f346fb7c79b85e", "6b2ad7a1", "d41bdd74f0dbbcb034ff01402a163736", "ae41363098fe07213fec440bb03be81aab0fb7f0", "afecd3e65dcb52c4c8625471842d007575e4cb33942ac4e6377014cce668ba4f", "6de164a9626d5a4f54d854ac158994f35a8e362ecc753f55182790934a2e0d06" }, // 28
  { "a963c3e895ff5a0be4824400518d81412f875fa50521e26e85eac90c04", "51e5475b", "bff43c6ee76dffa8850237aa11ec11b9", "ca408361c45d44c71e90fb6b4c69955d08c58ecd", "7ac86f1239e32eedaeaa8ed184445c8b017e9124a5d283cf4393fd80ad3996f0", "b760312bd1b279fc672479d21c5ed349e5fe96f08940237b4515452721c49a16" }, // 29
  { "03a18688b10cc0edf83adf0a84808a9718383c4070c6c4f295098699ac2c", "0807648c", "268c59a326b83e17f42bd7500c916290", "a9b323ca196695d80ce6cfb26ca9a8b77e51b008", "5e9c68da67265b87ded2f3b2a93744f5b7ec832419916aadf0ea78b63ef97432", "94fc255de4ef19c0da4b09b2e2fac21f20048b46f17c30685abe40d5c743f375" }, // 30
  { "84fb51b517df6c5accb5d022f8f28da09b10232d42320ffc32dbecc3835b29", "dddccc2a", "6b393afb85a556ff1b38ceef3ba946c6", "cda4605fb1409be66738df89f20f3da5e6609056", "9929cf1e6fac383f3a2fa322af8d125753bcf9c28ededb9e63a45da0cf5c5984", "39a4a0ffc4603698ae0a4f3d24b1bc42ac7a2d7d923e7a5d602453e82d5323c5" }, // 31
  { "9f2fcc7c90de090d6b87cd7e9718c1ea6cb21118fc2d5de9f97e5db6ac1e9c10", "c90368f7", "b4b5b22fea8d7a60d07859b46b03b810", "5eb1836714dd13760ec23a8187c3c64086dcc3f8", "ace84f09d49226d391e3704ff36b0cb5a61c0a0727e6bc5a7188e5c273a740db", "2f1a5f7159e34ea19cddc70ebf9b81f1a66db40615d7ead3cc1f1b954d82a3af" }, // 32
  { "de8f1b3faa4b7040ed4563c3b8e598253178e87e4d0df75e4ff2f2dedd5a0be046", "e43f6c2b", "c09b81300dfe5d57cd53b29971ef55ca", "2299eef7f22c57e489c29155e632b10d6ad28761", "072d632c7b4d6cf25f3c18336d572d22759d5a78e5cf9ee5f3d844f2b6345cb3", "1c57fe0e38cd3a124eaa6cd87f70a079bccc073a341e8c0eb1976fb3a3f7b774" }, // 33
  { "62f154ec394d0bc757d045c798c8b87a00e0655d0481a7d2d9fb58d93aedc676b5a0", "2aa78ff5", "c1b47551dbd87287e3786d29f0ead5c2", "b53c51b62b98bb6a897bdf2e4de297ee6f80d64f", "2d503f6f3432d37088b1890299259db30d158665604ea63e82cc43548412bd35", "a905603b186ef4f2d5b2d1bcfda504c68ed5eb9b0c7b7ea2a001575f5aa69e68" }, // 34
  { "b2dcfe9ff19e2b23ce7da2a4207d3e5ec7c6112a8a22aec9675a886378e14e5bfbad4e", "d9c9c459", "39a82f09125434582385b8b09ef042d8", "303ea353679f64e0e7ea72f308908091b3f798b6", "c4a3feb41cd26f040c26f0b0ca12f8e3d55f0bb39771ee087c5086118e098146", "fffd39f7c451788eb0316f429ea0a7c0ac8091657aca28f1560ed5775e8c4c12" }, // 35
  { "47f5697ac8c31409c0868827347a613a3562041c633cf1f1f86865a576e02835ed2c2492", "5b1508f1", "cdb044f567cde9d20b264add4edf6a56", "499279bf8d5c7ac1f0ae11de2a7a774bd949ad17", "cb9e4c92d9cf019f4c3156ab791350ad8e42e502f7f2eb64e47466aebbffd283", "6f55becd168e0939ba2fa090257b1727fc66491a44493279a5beacb9e3435324" }, // 36
  { "512a6d292e67ecb2fe486bfe92660953a75484ff4c4f2eca2b0af0edcdd4339c6b2ee4e542", "9c7afee9", "a3f7368cbeb89e1ed9564c147bc62ccf", "1aff151f3d6e3c71a2cfb9cd0170a1f907aa2e28", "5f4b5f2cebc6e5c7d8939273d3c63597efb8e7414b7373dfa4060041252f07ef", "84649bffcd48527b9288e8da5f52fbab2604dc5a91c4b0b87d477dbd7b40b6ae" }, // 37
  { "973cf2b4dcf0bfa872b41194cb05bb4e16760a1840d8343301802576197ec19e2a1493d8f4fb", "2466a23c", "91a3389423f3aad784cfa032e8511fac", "a950d6ce4683c8e9c97db7ec3ca8770ae1d78410", "6bcd52fae737be4465e3688ce0620b668d1b3b926bf12265bdcf215e22bee702", "d4055b4e3e2aea1c67cc99fd409d574e53e1e296cf9eef73c472ab92a6cb6609" }, // 38
  { "80beebcd2e3f8a9451d4499961c9731ae667cdc24ea020ce3b9aa4bbc0a7f79e30a934467da4b0", "9869fe61", "4e9f41ef61570fb59c1905c127a1dbb6", "d46154473fd626ed75429dedcb6d18c14b84bf09", "61c7b8427e946955efc51dcbe85c33f770f35c9f87cca931a220435cd5cb52c4", "5694ca2f3b9962226a87163ab38325bcdc898a732dfeb2c36db4eb88616b8741" }, // 39
  { "7abaa12ec2a7347674e444140ae0fb659d08e1c66decd8d6eae925fa451d65f3c0308e29446b8ed3", "30ec2a35", "59b97d4bb9621edd21508e983d1e0162", "50aa4e5b0d5aa3fe38a7b6539060a393f132e754", "7e9d4111cc710b6b24290fcab6934ad08cd4b239c1a0cbdde71f685f0a1e6fd9", "8cf287ad03ab4a74086620cfa4cce74f48fa5cdb15ec02b1f721736a4f849e60" }, // 40
  { "c88dee9927679b8af422abcbacf283b904ff31e1cac58c7819809f65d5807d46723b20f67ba610c2b7", "5a9f457c", "dd004f029f857a4e9acfdc516191dd0e", "baf9d3c7d2b18f36ac2981c7f071e63bbbfd3493", "2668d27f283bce5f7919d490d721aea6bbd0348332a2cde536dd4bc1912c55ad", "c5d5af22a4df9acd0c056fa30d8e240b679a20d4d2630260f779ff815ca82d7d" }, // 41
  { "01e43fe350fcec450ec9b102053e6b5d56e09896e0ddd9074fe138e6038210270c834ce6eadc2bb86bf6", "44d76f15", "28b66ebe60836815e0050c6dae6cb383", "a0a7388255f447285f5419ff96aad6f1818d6de0", "c60b5602cb8a1a23ec67b6c57ab41152ea1360a532b146a8e3195b2c23b32b48", "0ac75279adff65660464550a283fecd4e0610d88f35574c3d7ac5d22262a2fe8" }, // 42
  { "337023370a48b62ee43546f17c4ef2bf8d7ecd1d49f90bab604b839c2e6e5bd21540d29ba27ab8e309a4b7", "aef8f701", "66191acef6407facd6776248be2b2814", "deac10320e720100261ec67889ae36a13688c4e2", "612af005d7f47d3d7cd0e8cdcca4571139fef602e82e64e7e027189e5b1b8700", "81917ae290dbba17289a8a67e5c2e8b12d3dde0efe9f990198a1763ff4f3dda7" }, // 43
  { "6892540f964c8c74bd2db02c0ad884510cb38afd4438af31fc912756f3efec6b32b58ebc38fc2a6b913596a8", "a1739060", "72f332cb3d1ee64f1956eea0f9f65b64", "42b6406d40071927e77a0d7749de78a7f426b290", "42633916521313c491f53a8aed2de5647bd21befb8423e31397e3ba76e7cc43a", "138e75e72fddd927e591315af8d3aba280efa36230a3309a97bcde5a78c31589" }, // 44
  { "f5961dfd2b1ffffda4ffbf30560c165bfedab8ce0be525845deb8dc61004b7db38467205f5dcfb34a2acfe96c0", "2ad774c3", "e729ab5e0ed1eda842771b4cab4f7e24", "3e1b964d0dd2c054862c038488b8ab0f1c38f13b", "bb15e052c6167318eb92530ee2a6a38bbbb03888b27ccf17402dd91336742e7c", "21bcdad3fef3e5b859cb0912a2991efa661bad812747292ef0f79a8fcc6b4e98" }, // 45
  { "ca061a2eb6ceed8881ce2057172d869d73a1951e63d57261384b80ceb5451e77b06cf0f5a0ea15ca907ee1c27eba", "b0ecc329", "6886c2fe3bd64c5d7e0a92dd9d3de9c1", "75f7e1712c432f990d5d47bb410bc0ed1f01d340", "1debaf5b88a075e43a0ec8765fa3830b3e08655162b28ce9a9357c4424869fa5", "8d6fd9c559b0b4948f91337916084c0082a16a0755b0a00811096e973e48b3c8" }, // 46
  { "1743a77251d69242750c4f1140532cd3c33f9b5ccdf7514e8584d4a5f9fbd730bcf84d0d4726364b9bf95ab251d9bb", "26ce2541", "48a07b1571b3de06d65a88e95ca57b50", "2c2bb28f64a17b4054376a503bb9c57f1e142bf4", "de11c81dd4609233c6a2d73a3ac06a20e312e6e1c0f5d351bc72b3d5c40961a0", "1dd23ae7aadd61e712bdd82bd60a70dd9d66c9fd79dbfd8669e3eaabf7901cdc" }, // 47
  { "d8faba1f5194c4db5f176fabfff856924ef627a37cd08cf55608bba8f1e324d7c7f157298eabc4dce7d89ce5162499f9", "8ebccf97", "3dea64ea9ed114752e867afd704a9762", "b8be5ea10dee2d8190d82dd47b94d6a8019baec8", "ecd5464831f5a8b034f07b3ef7b96d096751d76425d0771bbfaeed9894721ccf", "34f8607ec10c092c1ba0b6565ce6197062c4e1a35a8e8c723e48a2d2416c3790" }, // 48
  { "be9684be70340860373c9c482ba517e899fc81baaa12e5c6d7727975d1d41ba8bef788cdb5cf4606c9c1c7f61aed59f97d", "46a4b59a", "83c390e922be9d42cf14d8df71bf3541", "7a6281ec0b58c82a80b1ee18e8bbf22e6d84df60", "171300d37d33b2f8942ed26aa86c67346fc0c9710c6e59a83472c4dafc033aef", "19a8577fc90fae5d6a6b2e0c1ff155515502cfa1757029c09bebbfa263d9a363" }, // 49
  { "7e15d2b9ea74ca60f66c8dfab377d9198b7b16deb6a1ba0ea3c7ee2042f89d3786e779cf053c77785aa9e692f821f14a7f51", "f5661d98", "730487d5390fd8a72bcde0109529f614", "6e17b4575af829c6ee18e24fb6eae024a9baaf49", "7863f2acd39baee07b57e2e65a391dc828c05de45821e52e3b908b43a9ad9705", "9d9dbb4ce7d01d009e72a66051acc16805e49f598cbe430c5d4c22a881a64b3f" }, // 50
  { "9a219be43713bd578015e9fda66c0f2d83cac563b776ab9f38f3e4f7ef229cb443304fba401efb2bdbd7ece939102298651c86", "97779492", "2c2ac042030f8f1645df0e9575bd2d41", "29309a4a739f0e6ac4ef1fd38871c9a02a326d10", "ee0924a0f948eba8bc731c0489da61d6665829fc2e6ea1b5378964f5a77dd7dc", "13f0d951b64481135466cfccbe52418cc1d03fb16b5b696c35d724f6f55cbb6d" }, // 51
  { "c8f2b693bd0d75ef99caebdc22adf4088a95a3542f637203e283bbc3268780e787d68d28cc3897452f6a22aa8573ccebf245972a", "2d2ad237", "d72991ae45a2f1deaf888c4e9886d3fe", "88970ef3bb5191e6927a639dc105835e1b98aaba", "f7f7c47d804f0d9455426e236676d6e9ddd91bf99e40e23220ca911d99d88ada", "fb2fe7b00b75c42305cf31de14d98f904e8c46dc57bb6f94c282ca8c13dc45db" }, // 52
  { "ec0f99711016c6a2a07ad80d16427506ce6f441059fd269442baaa28c6ca037b22eeac49d5d894c0bf66219f2c08e9d0e8ab21de52", "69f4b6eb", "590fcad19889b907e3d6bbdf991edc93", "a63c6fd614d977f015fcc29936dfbffc9e8f2d33", "ee99da04f780abe64d2c1ee1170e7f678c50683a7b9303a84678c6ebdf9b9a7f", "d54cbf7d5c80ae11a0d0bad4e95ab18b5f07c970621f3936447a48eef818d06e" }, // 53
  { "0dc45181337ca32a8222fe7a3bf42fc9f89744259cff653504d6051fe84b1a7ffd20cb47d4696ce212a686bb9be9a8ab1c697b6d6a33", "27569834", "e087a2fb0e175b748d68833fbddad14e", "01c8e2d5274a8daf51bb207eee328c33b49592f1", "860c4d344cd31e574e20ae9a54ed146f690823930e43947e89adfeda3da669de", "ff050a45adeef4cfc7d964102ba877c80320a37794893e6865965ec2547cd4c9" }, // 54
  { "de286ba4206e8b005714f80fb1cdfaebde91d29f84603e4a3ebc04686f99a46c9e880b96c574825582e8812a26e5a857ffc6579f63742f", "43ab2765", "1c4f5048955f692961be8682e7226025", "e81bed804597822ac47ca7a507976972eece5c60", "99a9fa276e7471535a13e41abdb1dd5c1013ed1f4d57a4c7b9433455d3cdc705", "1bc1bcc70f638958db1006af37b02ebd8954ec59b3acbad12eacedbc5b21e908" }, // 55
  { "eebcc18057252cbf3f9c070f1a73213356d5d4bc19ac2a411ec8cdeee7a571e2e20eaf61fd0c33a0ffeb297ddb77a97f0a415347db66bcaf", "4d3ce864", "6d0557d282d4ddbfa3f0607030db59ac", "d493f943e6d7e52989990f1bb88c835e9a14ab59", "c8d39c9dabb62cb284be55658b05412b50ff3eda8ac98ae6bc616f466aeb2650", "f7bde239ad087aa7dabe42cc4d3c49380a026cd239a7faaf34a2233469a44a4d" }, // 56
  { "416b5cdc9fe951bd361bd7abfc120a5054758eba88fdd68fd84e39d3b09ac25497d36b43cbe7b85a6a3cebda8db4e5549c3ee51bb6fcb6ac1e", "a49c059d", "2a51205e846de5953d7e1c6900fc574c", "24a9ea1d842750fb805a8e1985d7cfaeca799fa0", "03f7b846ea8f9e26760eeaa30eae500646819842d6af87ca64275b865aaf43f7", "ef845aac2aaf0a793108204ff380e0a30f2558e7acde4531ab22f8ec79e26a69" }, // 57
  { "5c5faf66f32e0f8311c32e8da8284a4ed60891a5a7e50fb2956b3cbaa79fc66ca376460e100415401fc2b8518c64502f187ea14bfc9503759705", "63822070", "2d4d21e2117980b30ee1827876ae37f7", "45ec45c12ae8056e31df5578659ac18b077e0337", "463a6a7d0765f0a520f4dff288c4caa7c4c0ce3080e3703cd47122a7ee8b9434", "26db514e01e034c678b636d40ba367da2f37f67078bb576ff2b8559b3517484d" }, // 58
  { "7167e1e02be1a7ca69d788666f823ae4eef39271f3c26a5cf7cee05bca83161066dc2e217b330df821103799df6d74810eed363adc4ab99f36046a", "a2c861c5", "8d04f5ae0093555f98532d29e062138c", "ea91f748c7a9137eda2a82d7e8e9dbe54d574949", "c82776eca46928e0d5b3d1c43db40953cce11013cb3528fec5b882fc5b286fc8", "5dbd4b558463196211465c1fc32401fc2d8e41ebc5e6badd1d8f7c4f090f728f" }, // 59
  { "2fda311dbba27321c5329510fae6948f03210b76d43e7448d1689a063877b6d14c4f6d0eaa96c150051371f7dd8a4119f7da5c483cc3e6723c01fb7d", "0bf07be9", "0d84254eb21804f52cc6155c736bfe2b", "905fac724e298c9849ae82c0c0d3a494a8060085", "55d4462e8486ebc14e2f5ba7f573330faf3a0d56bdf7701ee2820aba265d7ac0", "355c79fd6e6fa88ed402b6979fde1ed805498abeb101f4231b5d64d1439d552d" }, // 60
  { "95d1474a5aab5d2422aca6e481187833a6212bd2d0f91451a67dd786dfc91dfed51b35f47e1deb8a8ab4b9cb67b70179cc26f553ae7b569969ce151b8d", "cb5e3049", "dca6b7cded7224dc17e8c7e506f4e011", "b17fb3167bc83a7375ff6ddcd5f0b552ad9ddc41", "4d78228bf419b23d867082d8d5c066a4aee56a9bb54224d3b5cbd2c04364d99c", "3d9c9bf09d88211c7e0056112d073ee85d00acaa4da7a668fa017b3273cd4d4b" }, // 61
  { "c71bd7941f41df044a2927a8ff55b4b467c33d089f0988aa253d294addbdb32530c0d4208b10d9959823f0c0f0734684006df79f7099870f6bf53211a88d", "4eabb06f", "fa630a5284e5180afa75d6ba9a0ff421", "5792719abbd47647358eb65529abd4136d501af5", "48d4ed4341aafba1f02bbf72eeaf2bf5991c04ea3c643d7665f0130fffdc9165", "67980d28e2e658e7a24a2593a28167a13d907d06f47729d47ca4fe1772f8b3df" }, // 62
  { "f57c64006d9ea761892e145c99df1b24640883da79d9ed5262859dcda8c3c32e05b03d984f1ab4a230242ab6b78d368dc5aaa1e6d3498d53371e84b0c1d4ba", "8ffc4b50", "90d5671bdc15f8f96c3745f6f6020a8e", "632ee5446b709013fba8123b67e49dc7bdcc4c4f", "ce122fb56c82bf0cf7953b837e2f00cb0546f5b5d91f7af3480f659ed6152390", "a8df6b76df41994f7593f1a81967e77ee180e31183d1c4a569db854e61e99b05" }, // 63
  { "e926ae8b0af6e53176dbffcc2a6b88c6bd765f939d3d178a9bde9ef3aa131c61e31c1e42cdfaf4b4dcde579a37e150efbef5555b4c1cb40439d835a724e2fae7", "ded134c1", "f8885d6cda92c999dc4bee554df7dd2c", "6c4664cb736cd563f74f52cea42e33d6d617f153", "f4a1a02e8e35822107cc08b5b21b661c058e2825f3c7cb2a3b6d40f3ae89211b", "27a6441ee939b46e2c378d7afeb0e891c47a28120e488eff0ab71af08788ceb3" }, // 64
  { "16e8b3d8f988e9bb04de9c96f2627811c973ce4a5296b4772ca3eefeb80a652bdf21f50df79f32db23f9f73d393b2d57d9a0297f7a2f2e79cfda39fa393df1ac00", "e891cf16", "09ceb3a6fa3e2d38467a6969d43f6587", "6ba94f05cfa29501ff47ae917e18763e063229da", "16b1449186ef6d27ddf9f8ddfe23c59e51a953833c7df2e8c6a7528403f3ba68", "c4bb067383002db44ca773918bb74104b604a583e12b06be56c270f8b43512f2" }, // 65
  { "fc424eeb27c18a11c01f39c555d8b78a805b88dba1dc2a42ed5e2c0ec737ff68b2456d80eb85e11714fa3f8eabfb906d3c17964cb4f5e76b29c1765db03d91be37fc", "82e3941f", "09f55194b57e25646de7c5e4a8635f5e", "1e2895343ba31a9e32730f8156c68369e3f4132c", "9d91ce1295f7acca7bdb2e2ff0794e5e2917509fe03bbcfb34bc8dd7e536b8fb", "ae773915ca642d80413330c9e0ee9bd06653c0023c5c0277100f3b1526eaa51d" }, // 66
  { "abe3472b54e72734bdba7d9158736464251c4f21b33fbbc92d7fac9a35c4e3322ff01d2380cbaa4ef8fb07d21a2128b7b9f5b6d9f34e13f39c7ffc2e72e47888599ba5", "e73f9991", "d561fc54a4d61467f7d72ea037bb9332", "ea1c325d0e91a757e2106792943361d47ce99bee", "f1737040e38e73ab3b4085ec8e1acf1e055a1ed8411e6cf867d0a5dca56a3364", "1cf9d6ce9cb658556b76cd7eba3e51393699ad500b1ab3f56172748db7f59667" }, // 67
  { "36f9f0a65f2ca498d739b944d6eff3da5ebba57e7d9c41598a2b0e4380f3cf4b479ec2348d015ffe6256273511154afcf3b4b4bf09d6c4744fdd0f62d75079d440706b05", "ae719e56", "313c5846da0836226ecbf50c324fb7c5", "0082b9a8ab38b32ac364e5f1a656cfe98ef9c931", "df0cd17c3fd3885653849bc8be8cad1f2171755e05176d448dc466fdb94ce780", "8d60e889e2b1020dad4b523301f5f6bbab6c781af276085af6765546fcfb95ac" }, // 68
  { "abc87763cae1ca98bd8c5b82caba54ac83286f87e9610128ae4de68ac95df5e329c360717bd349f26b872528492ca7c94c2c1e1ef56b74dbb65c2ac351981fdb31d06c77a4", "6c4cd72d", "53bfe40050067274fe7482d2a3b7986b", "328136f32226dc14f7e9dee5ba67863b669cb0d7", "6fe7f18c476330654ad42917435a5dd906c1c35f863cb2a8147a9fa10aa19c91", "dd4ff4b530552f48af9a7530a6464819ed1a5b733084f709e41daf1acb35ecfd" }, // 69
  { "94f7ca8e1a54234c6d53cc734bb3d3150c8ba8c5f880eab8d25fed13793a9701ebe320509286fd8e422e931d99c98da4df7e70ae447bab8cffd92382d8a77760a259fc4fbd72", "c957294b", "58a4f59c5a014d0d19f4b0807d3883db", "45905089a697d8542c78e1d206a0d87430fc0789", "54fe7d51e0cd082a42a4972acfdf8c59406c89ef95b79d659a84a0d07d121069", "7ac8d4bb53fc434dd8712daefeb474668f541418e6f617dba523d8392eb0766e" }, // 70
  { "13bd2811f6ed2b6f04ff3895aceed7bef8dcd45eb121791bc194a0f806206bffc3b9281c2b308b1a729ce008119dd3066e9378acdcc50a98a82e20738800b6cddbe5fe9694ad6d", "22bd0ff5", "bc3db75037ec1773fb11045a256001bd", "c29ad52ef807b4f73f3ec0b20999a996b3e462cd", "6feab1c9d115cc82efe3631535e964c3eeb5c3dad4c38d837717f8f10a3357b1", "f7b0e15a63232a2b800b23b311d357617ddfd1293e1ffe3f772692ade3427152" }, // 71
  { "1eed9cba179a009ec2ec5508773dd305477ca117e6d569e66b5f64c6bc64801ce25a8424ce4a26d575b8a6fb10ead3fd1992edddeec2ebe7150dc98f63adc3237ef57b91397aa8a7", "0ab24bd5", "9022f5cdff2c1f55ac3f5270f8d43484", "8b78f85b603c4b896cac77b41edee07c56d14058", "046155a4d0e52a53fc745278ded12590875fde9b66fa4e40a6638c1504f6d435", "b3d05af7e8c406a7c2709223791d3f5f4b3129329993220053a36293ac2b0e06" }, // 72
  { "ba5b67b5ec3a3ffae2c19dd8176a2ef75c0cd903725d45c9cb7009a900c0b0ca7a2967a95ae68269a6dbf8466c7b6844a1d608ac661f7eff00538e323db5f2c644b78b2d48de1a08aa", "8368ecf5", "92c203258dfb11755b1a6f3d15095f45", "e0a01e53a373265566a422f5209346605eca2252", "450effce3b3be76285be139ad8c15cdb36d847a70122e7754cc50da7b4f262e6", "6c47e2ea4ba29e17792defc4b707754c4664bde15168a5100bf881ec7c02b258" }, // 73
  { "0efa26ac5673167dcacab860932ed612f65ff49b80fa9ae65465e5542cb62075df1c5ae54fba4db807be25b070033efa223bdd5b1d3c94c6e1909c02b620d4b1b3a6c9fed24d70749604", "f5fc8790", "c125928b6cdf8b88f30efaacef4acba0", "732dbb9df2f07abc0ba482376a401acb1652fd1a", "88f8922134a0dfd8cf733e69a67f79695c157a12f004e0f41f47dbe25e929f11", "82a66bed668dcc14af12c14c976ce650049e9d1d9969b83d1dd3b6f1c07d252b" }, // 74
  { "bbfd933d1fd7bf594ac7f435277dc17d8d5a5b8e4d13d96d2f64e771abbd51a5a8aea741beccbddb177bcea05243ebd003cfdeae877cca4da94605b67691919d8b033f77d384ca01593c1b", "07c73070", "2ce5ec25b22239c42ad1e1fd4a38e7f8", "1196665356621ac4b74f7cb453a695ff51fe13a0", "6abd3225cde2afc0da502567790af919681ae1bee565192a06e5e34df7cdfe4e", "2f21d07d7b10683b9ac7a63e9fcc70cf9f887cb905f9bff5332551288b288524" }, // 75
  { "90078999fd3c35b8afbf4066cbde335891365f0fc75c1286cdd88fa51fab94f9b8def7c9ac582a5dbcd95817afb7d1b48f63704e19c2baa4df347f48d4a6d603013c23f1e9611d595ebac37c", "905d3872", "fa79da4e5b2df87ce3cc98ab763fd19c", "16b3a27baeeecb4c4c66c7f235fbd4f6c5839145", "0cbd201eca6a8fabf81c7377047a4a86f6dff090d665381fd884c6b5836b0902", "80202f01e7140db4fee490dcc50afafdf6a48ca33d362c7875b8e8db9c9d0655" }, // 76
  { "64105eca863515c20e7cfbaa0a0b8809046164f374d691cdbd6508aaabc1819f9ac84b52bafc1b0fe7cddbc554b608c01c8904c669d8db316a0953a4c68ece324ec5a49ffdb59a1bd6a292aa0e", "7e11cb91", "b9c451f86bc03e42fca7d2400609b188", "61d6f9fccf0a8c486dfa7df4417dc4d0c4e59149", "e30a878fdab9b75fc3d1f8ca1ea9c754817de4a471aa8e2abd6a7526e36274c5", "b2330a189047e3117479a2f20b3407a7d119e4ad431fe06ff1ff2a106f2ab3a2" }, // 77
  { "d4654be288b9f3b711c2d02015978a8cc57471d5680a092aa534f7372c71ceaab725a383c4fcf4d8deaa57fca3ce056f312961eccf9b86f14981ba5bed6ab5b4498e1f6c82c6cae6fc14845b3c8a", "dcdff841", "4551bc9250abb5607cca78ca71137a3f", "a95f70deef0c1733a02e6297a67aa61f0356e005", "9b163642ad529f4f0ac03b31cc22752599fd3cc3abdca1124cbce15eab11021e", "bb9b9bb685c241f8d63fdbf0dbaabcef7075add7ba405a2fffe7ad5b23e021c7" }, // 78
  { "12d9394888305ac96e65f2bf0e1b18c29c90fe9d714dd59f651f52b88b3008c588435548066ea2fc4c101118c91f32556224a540de6efddbca296ef1fb00341f5b01fecfc146bdb251b3bdad556cd2", "9ccb3cf0", "0dc5922d3935802af173a0825b8793cd", "6a59742f6d780f0161427835f743187e7c4de6c2", "e9d510eb338e4def24410eab6e26845a721aa9feba233d225f18f9a4d165c0f8", "f8316a367aa0316da3562f319d522e81f4a8bd2e2108d2532126f4a903704ba3" }, // 79
  { "871a0d7a5f36c3da1dfce57acd8ab8487c274fad336bc137ebd6ff4658b547c1dcfab65f037aa58f35ef16aff4abe77ba61f65826f7be681b5b6d5a1ea8085e2ae9cd5cf0991878a311b549a6d6af230", "c37eb643", "b14fd7247fb0600a4ee58d7d02c54573", "5ee0c3e4b737f3c6eb0537c6dba47e8e33334a39", "3bbc51465e6ad6c102c41cf61c0a510d191a522e7a8981eef519149d1bca5fe9", "89e3ebd02b229cd759612a5521d867ab2a1594bc0b1fe6a78b7954ccc84caf03" }, // 80
  { "e90b4ffef4d457bc7711ff4aa72231ca25af6b2e206f8bf859d8758b89a7cd36105db2538d06da83bad5f663ba11a5f6f61f236fd5f8d53c5e89f183a3cec615b50c7c681e773d109ff7491b5cc22296c5", "ba83a755", "a7b5bb4aa7b91d2853ec40c62ae71adb", "93e5e5a709b797bbb6e77a7ead3edec6d77d463d", "2ab2197e676517e8e900f69dbbfb6251e5dae049432d18adbdee892f42601e73", "2e7cc875305ea6bb9c2fc770b9d84fd93b96405df9b93307f6b5de26e135724c" }, // 81
  { "e728de62d75856500c4c77a428612cd804f30c3f10d36fb219c5ca0aa30726ab190e5f3f279e0733d77e7267c17be27d21650a9a4d1e32f649627638dbada9702c7ca303269ed14014b2f3cf8b894eac8554", "8bac7df0", "3bed3364dda24e4f121971960ace8cd6", "80ab947730a8b954b0e0108f9add9808ad9d4d4c", "a245a9c8b82fcf89b008b8f68393bdbf70a7750efa9f946a493025f5b929e398", "ecab75f28a728429cb433ec13310d1b850ccf522c38d2fa6dfa489963d6d6ca7" }, // 82
  { "6348f229e7b1df3b770c77544e5166e081850fa1c6c88169db74c76e42eb983facb276ad6a0d1fa7b50d3e3b6fcd799ec97470920a7abed47d288ff883e24ca21c7f8016b93bb9b9e078bdb9703d2b781b616e", "8666f487", "0b5846abc9ec2f73f95a046a98db99e5", "6d8d4d535d9478bfe55bc439bd72aa4ca059994f", "40319d72d16dd3b02e5049b28dd4de6bd6263796085069184ca868912d1a39ea", "021c9459d1451f3da4c07c029a8681945c87c5bebc6c30da1d95c5c49d8ab95c" }, // 83
  { "4b127fde5de733a1680c2790363627e63ac8a3f1b4707d982caea258655d9bf18f89afe54127482ba01e08845594b671306a025c9a5c5b6f93b0a39522dc877437be5c2436cbf300ce7ab6747934fcfc30aeaaf6", "b9b607f0", "8e7c9e38008a99bc26850bdcfa296fd7", "5a991f5a462d57c678f8b1a853d5e63510c0c01f", "9885b7b4d61caee20fcbe9a902496071f3113f34d144929891ee711b12f6d1db", "4642e21622f15b09b9413659680116bf2f96cac2384b8c79f1328d5dd36d7a01" }, // 84
  { "08461f006cff4cc64b752c957287e5a0faabc05c9bff89d23fd902d324c79903b48fcb8f8f4b01f3e4ddb483593d25f000386698f5ade7faade9615fdc50d32785ea51d49894e45baa3dc707e224688c6408b68b11", "07839217", "03e0732d64855293605a4ffea43e2151", "e734c52c2930b653dd5b01e04fde3ad7b9eaa51c", "64278b8ed65d1d1ee032d6289d74f7d5637d0538e7b05bcd099ca7cc8f6263e9", "8daa47c3572157266ad0276d5926aff2872f06b0cd7b974a80d7a6827d41d782" }, // 85
  { "68c8f8849b120e6e0c9969a5866af591a829b92f33cd9a4a3196957a148c49138e1e2f5c7619a6d5edebe995acd81ec8bb9c7b9cfca678d081ea9e25a75d39db04e18d475920ce828b94e72241f24db72546b352a0e4", "d74ac160", "bafd00316db76387bed7c84492d70158", "7e1b8fa40e87f9b12d40a1fcfd66b2ca708540d3", "3a4145a03567aae008db8fed2a58f616dcfa6d345ae38aa27b9e2ead32768a9e", "345365232ce9afc655dce4bac23f43c8acbdf9016d4bc2344be8d396a4919c34" }, // 86
  { "b8d56472954e31fb54e28fca743f84d8dc34891cb564c64b08f7b71636debd64ca1edbdba7fc5c3e40049ce982bba8c7e0703034e331384695e9de76b5104f2fbc4535ecbeebc33bc27f29f18f6f27e8023b0fbb6f563c", "60457106", "65ec6a553b431e4fa351cf2dfc6c1b53", "d887f88a626f98cad59e0a5b2484189bb1accc6b", "c50b8c10e4dbbcd0055d9a81a89f2ac18b709715377eb4048edbc4b497165f5a", "f52e102e57293878c28f29deb47792324fe455a62fa7441aabcc16a9cfc40ffa" }, // 87
  { "0d58ac665fa84342e60cefee31b1a4eacdb092f122dfc68309077aed1f3e528f578859ee9e4cefb4a728e946324927b675cd4f4ac84f64db3dacfe850c1dd18744c74ceccd9fe4dc214085108f404eab6d8f452b5442a47d", "966eb885", "8f37ffb065d2ca3e5e40930455518773", "3103211925d1886b7bfe73c42f24e000ddde8e01", "63deff17e210cd39682f253d819cfb454d6434bb72aa36d3074c808f051043d5", "2b89aa88b1b7f9f8ea461c4c5cae4829125f45f5697deadb8db2e964524c0d91" }, // 88
  { "1755e2d2e5d1c1b0156456b539753ff416651d44698e87002dcf61dcfa2b4e72f264d9ad591df1fdee7b41b2eb00283c5aebb3411323b672eaa145c5125185104f20f335804b02325b6dea65603f349f4d5d8b782dd3469ccd", "a4fb2fb2", "52d15ee0e65cc07d84370f420f3f4ccd", "1baeeea41fcf4bc3cc4178d77475f869369b8a36", "fb76aa04f9f2538c4262e8cd4ca5053ea2e2b082b97a484293fce02d97abe341", "3f3092365982c0b4278055beee9032ff9d1060e03c3b087e1a6197defc707e1a" }, // 89
  { "b180de1a611111ee7584ba2c4b020598cd574ac77e404e853d15a101c6f5a2e5c801d7d85dc95286a1804c870bb9f00fd4dcb03aa8328275158819dcad7253f3e3d237aeaa7979268a5db1c6ce08a9ec7c2579783c8afc1f91a7", "5412b36e", "ae8786808d7ce1a0d9a9226befb0bdca", "ab82cef5607ffa69e218ff71fc0d2d97bf713d03", "4582b15b38b27dca503ef8423b249a7703e987953139129c1468a3ba6b826740", "3c74aae2f340a24178cbab51004cba1aac3d91133c300715ea82c177269c0556" }, // 90
  { "cf3583cbdfd4cbc17063b1e7d90b02f0e6e2ee05f99d77e24e560392535e47e05077157f96813544a17046914f9efb64762a23cf7a49fe52a0a4c01c630cfe8727b81fb99a89ff7cc11dca5173057e0417b8fe7a9efba6d95c555f", "8724d307", "7dd591d07265406cc377020ac6c7e058", "6907d863d797deb8e46bc94ad05b6bef242a15d9", "7a41a251c2de39f9593b9808d89eb31958cec525b31d2e7a373dc29ee33ad9db", "0157c4ba44618ded11e9800afa07a0d5b6c711fc16a576c5edb71c4cc6894f82" }, // 91
  { "072fc02340ef99115bad72f92c01e4c093b9599f6cfc45cb380ee686cb5eb019e806ab9bd55e634ab10aa62a9510cc0672cd3eddb589c7df2b67fcd3329f61b1a4441eca87a33c8f55da4fbbad5cf2b2527b8e983bb31a2fadec7523", "b4e5de52", "218579c794ef71c9da317e227e90d058", "9ba690ac8b7a22662b244fc7f27c8723c3fc649e", "e146431158a7db63496e7fbb4741b820ce288a1758495ea8ef6061adbc36cfb9", "8d53dba107aaacb8422d6667f6778839f8965f8e4c8f4a851284cc91168a9030" }, // 92
  { "76eecf956a52649f877528146de33df249cd800e21830f65e90f0f25ca9d6540fde40603230eca6760f1139c7f268deba2060631eea92b1fff05f93fd5572fbe29579ecd48bc3a8d6c2eb4a6b26e38d6c5fbf2c08044aeea470a8f2f26", "f6ca3db4", "540f04cc19dea131532b643fb63cfae7", "e3b917152cab357dc3585fffc2d95e2337bd9b6f", "05f8979573501c8fb1778a9d38e9cad4ef481e5d6f6bdffb4fc642b5f3ce22c9", "5163f02233e332ad9be32c2346c9fcfe39afa5fbe9bc1cfeb92f4920155b20ec" }, // 93
  { "7adc0b6693e61c269f278e6944a5a2d8300981e40022f839ac644387bfac9086650085c2cdc585fea47b9d2e52d65a2b29a7dc370401ef5d60dd0d21f9e2b90fae919319b14b8c5565b0423cefb827d5f1203302a9d01523498a4db10374", "567891ac", "d859f008f48753ead4e62f52ca11377f", "233920ef506e9c59481d306d89cfccbb2fdbb2d5", "5ba07a5acf0fe4c89df8171896812ffea2b2de5185df097da8bde2635f512f4e", "faaf0e95217ca4b1568751ef2e4cd341d9ec33e16600bf09b92c6f1a6df84d2e" }, // 94
  { "e1fffa9826cce8b86bccefb8794e48c46cdf372013f782eced1e378269b7be2b7bf51374092261ae120e822be685f2e7a83664bcfbe38fe8633f24e633ffe1988e1bc5acf59a587079a57a910bda60060e85b5f5b6f776f0529639d9cce4bd", "c6835842", "05b12d9ac1c9854ebc86f00080321bc4", "f8429fe37ed6a336d46ab0e510d6772f0587d3bb", "65ac6f5061759518913cde199d49ec9e06c19e97c42eb99ab4f835eb8a4ab2e2", "b2c175d9d92aaa9ee72672f995b8dfd2daaf6555a0327a508218a9b447f00be8" }, // 95
  { "69f9abba65592ee01db4dce52dbab90b08fc04193602792ee4daa263033d59081587b09bbe49d0b49c9825d22840b2ff5d9c5155f975f8f2c2e7a90c75d2e4a8040fe39f63bbafb403d9e28cc3b86e04e394a9c9e8065bd3c85fa9f0c7891600", "4c61dddb", "f3642e61b5c0042af24a3571d7c9c239", "267a3f3a6fe13900f2bf1c9c360cdef18a6d9862", "4faef6b1ced3843526e9c93262647450dc7a68cda7e17f611e01bc6737d92c1e", "fb5388122306d37cee790cad1d3cddba8e9a93d5f9d78288b052482739c883fd" }, // 96
  { "38a10a352ca5aedfa8e19c64787d8e9c3a75dbf3b8674bfab29b5dbfc15a63d10fae66cd1a6e6d2452d557967eaad89a4c98449787b0b3164ca5b717a93f24eb0b506ceb70cbbcb8d72b2a72993f909aad92f044e0b5a2c9ac9cb16a0ca2f81f49", "eb65cf3e", "b7d46788d692d387300f5bfaa379ed18", "1594d253f40cabdafbe5eae70b7f6d4d142e9c1c", "9707054caf9ce8f2eb3e4304e3018beee27516bce6bf507d68adf7485b8c002f", "1c2f8d418ff6718b18dd4c756dcc8ed0f4755e8c22497a6cc19f8d7ae7fd2da7" }, // 97
  { "6d8c6e449bc13634f115749c248c17cd148b72157a2c37bf8969ea83b4d6ba8c0ee2711c28ee11495f43049596520ce436004b026b6c1f7292b9c436b055cbb72d530d860d1276a1502a5140e3c3f54a93663e4d20edec32d284e25564f624955b52", "6322e90d", "7d8e166acc1d95fc2f9098b02d431283", "25b53442fd71250f2c9a5c9df5655bfb8ead4b2e", "89e1ee5e7b902293bcb91098a2691cdc2ec0444bfce6c0078e7f2e27c06e9459", "7ea8116e6434c1caa049069dbbd9b6f0e9dc6cdfd6a889343d3b2652803078fc" }, // 98
  { "6efcbcaf451c129dbe00b9cef0c3749d3ee9d41c7bd500ade40cdc65dedbbbadb885a5b14b32a0c0d087825201e303288a733842fa7e599c0c514e078f05c821c7a4498b01c40032e9f1872a1c925fa17ce253e8935e4c3c71282242cb716b2089ccc1", "e7d1d1e5", "ac2ffed693bfcb55c8a717af6c4fa348", "ca4cf03895a389d8e926b9cca06c457db3672cf8", "3dc3e4bbc7e26c406c38c139a2c864bd7dbe71347bfc02f488c6874d90e1a741", "736d888751faac4d8e78b45b95abb15d40d98d8038c7225be0f523d5439ea5b6" }, // 99
  { "433c5303131624c0021d868a30825475e8d0bd3052a022180398f4ca4423b98214b6beaac21c8807a2c33f8c93bd42b092cc1b06cedf3224d5ed1ec29784444f22e08a55aa58542b524b02cd3d5d5f6907afe71c5d7462224a3f9d9e53e7e0846dcbb4ce", "5c444498", "9dc41264137166fe20aebb253ecce43e", "e9c3b6728e90f15a3703d1b9906e8f957ce0d4e5", "19acbb45e086963576fa1847f933f6ed78e777a4a27aca0609969362a72e3abf", "90e10b1ca8d352794d7dbd7bae410bef25f0ec7d080e053f48674237e33ea45f" } // 100
};


// return number of failed hashes
template <typename HashMethod, typename Container>
int check(const Container& input, const std::string& expectedResult)
{
  HashMethod hasher;
  std::string hash = hasher(&input[0], input.size());
  if (hash == expectedResult)
    return 0;

  // error
  std::cerr << "hash failed ! expected \"" << expectedResult << "\" but library computed \"" << hash << "\"" << std::endl;
  return 1;
}


// same as above for SHA3/Keccak with variable hash size
template <typename HashMethod, int HashSize, typename Container>
int check(const Container& input, const std::string& expectedResult)
{
  HashMethod hasher = HashMethod(typename HashMethod::Bits(HashSize));
  hasher.add(&input[0], input.size());
  std::string hash = hasher.getHash();
  if (hash == expectedResult)
    return 0;

  // error
  std::cerr << "hash/" << HashSize << " failed ! expected \"" << expectedResult << "\" but library computed \"" << hash << "\"" << std::endl;
  return 1;
}


// same as above but convert input from hex to raw bytes first (can contain zeros)
template <typename HashMethod, typename InputContainer, typename KeyContainer>
int checkHmac(const InputContainer& input, const KeyContainer& key, const std::string& expectedResult)
{
  std::string hash = hmac<HashMethod>(&input[0], input.size(), &key[0], key.size());
  if (hash == expectedResult)
    return 0;

  // error
  std::cerr << "hmac hash failed ! expected \"" << expectedResult << "\" but library computed \"" << hash << "\"" << std::endl;
  return 1;
}


// convert from hex to binary
std::vector<unsigned char> hex2bin(const std::string& hex)
{
  std::vector<unsigned char> result;
  for (size_t i = 0; i < hex.size(); i++)
  {
    unsigned char high = hex[i] >= 'a' ? hex[i] - 'a' + 10 : hex[i] - '0';
    i++;
    unsigned char low  = hex[i] >= 'a' ? hex[i] - 'a' + 10 : hex[i] - '0';
    result.push_back(high * 16 + low);
  }
  return result;
}


// here we go !
int main(int argc, char** argv)
{
  int errors = 0;

  // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
  // or more compact overview: http://www.di-mgt.com.au/sha_testvectors.html
  std::string empty;
  std::string abc = "abc";
  std::string abc448bits = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
  std::string abc896bits = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
  std::string million(1000000, 'a');

  std::cout << "test SHA1 ...\n";
  errors += check<SHA1>(empty,      "da39a3ee5e6b4b0d3255bfef95601890afd80709");
  errors += check<SHA1>(abc,        "a9993e364706816aba3e25717850c26c9cd0d89d");
  errors += check<SHA1>(abc448bits, "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
  errors += check<SHA1>(abc896bits, "a49b2446a02c645bf419f995b67091253a04a259");
  errors += check<SHA1>(million,    "34aa973cd4c4daa4f61eeb2bdbad27316534016f");

  std::cout << "test SHA2/256 ...\n";
  errors += check<SHA256>(empty,      "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
  errors += check<SHA256>(abc,        "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
  errors += check<SHA256>(abc448bits, "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
  errors += check<SHA256>(abc896bits, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1");
  errors += check<SHA256>(million,    "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");

  std::cout << "test SHA3/256 ...\n";
  errors += check<SHA3>(empty,      "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a");
  errors += check<SHA3>(abc,        "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532");
  errors += check<SHA3>(abc448bits, "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376");
  errors += check<SHA3>(abc896bits, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18");
  errors += check<SHA3>(million,    "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1");

  // next test case produced an error until February 2015, reported by Gary Singer
  // note: automatic test case 71 failed, too, same bug
  std::cout << "test SHA3/512 ...\n";
  SHA3 sha3_512(SHA3::Bits512);
  std::vector<unsigned char> sha3bug = hex2bin("13bd2811f6ed2b6f04ff3895aceed7bef8dcd45eb121791bc194a0f806206bffc3b9281c2b308b1a729ce008119dd3066e9378acdcc50a98a82e20738800b6cddbe5fe9694ad6d");
  if (sha3_512(sha3bug.data(), sha3bug.size())
      != "def4ab6cda8839729a03e000846604b17f03c5d5d7ec23c483670a13e11573c1e9347a63ec69a5abb21305f9382ecdaaabc6850f92840e86f88f4dabfcd93cc0")
  {
    std::cerr << "SHA3/512 bug present" << std::endl;
    errors++;
  }

  // hex conversion failed for SHA3/224 (last eight hex digits [32 bits] were missing)
  // reported by Alexander Moch in March 2015
  std::cout << "test SHA3/224 ...\n";
  SHA3 sha3_224(SHA3::Bits224);
  if (check<SHA3, SHA3::Bits224>(empty, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"))
  {
    std::cerr << "SHA3/224 bug present" << std::endl;
    errors++;
  }
  std::cout << "test Keccak/224 ...\n";
  Keccak keccak224(Keccak::Keccak224);
  if (keccak224("") != "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd")
  {
    std::cerr << "Keccak/224 bug present" << std::endl;
    errors++;
  }

  // check all automatically generated testsets
  std::cout << "generic testsets (CRC32,MD5,SHA1,SHA256,SHA3) ..." << std::endl;
  for (size_t i = 0; i < NumTests; i++)
  {
    errors += check<CRC32 >(hex2bin(testset[i].input), testset[i].crc32b);
    errors += check< MD5  >(hex2bin(testset[i].input), testset[i].md5);
    errors += check< SHA1 >(hex2bin(testset[i].input), testset[i].sha1);
    errors += check<SHA256>(hex2bin(testset[i].input), testset[i].sha256);
    errors += check< SHA3 >(hex2bin(testset[i].input), testset[i].sha3_256);
  }

  // HMAC MD5 and SHA1 test vectors from RFC2202 http://www.ietf.org/rfc/rfc2202.txt
  std::cout << "test HMAC(MD5) ...\n";
  errors += checkHmac< MD5  >(std::string("Hi There"),
                              hex2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
                              "9294727a3638bb1c13f48ef8158bfc9d");
  errors += checkHmac< SHA1 >(std::string("Hi There"),
                              hex2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
                              "b617318655057264e28bc0b6fb378c8ef146be00");
  errors += checkHmac< MD5  >(std::string("what do ya want for nothing?"),
                              std::string("Jefe"),
                              "750c783e6ab0b503eaa86e310a5db738");
  errors += checkHmac< SHA1 >(std::string("what do ya want for nothing?"),
                              std::string("Jefe"),
                              "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79");
  errors += checkHmac< MD5  >(hex2bin("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "56be34521d144c88dbb8c733f0e8b3f6");
  errors += checkHmac< SHA1 >(hex2bin("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "125d7342b9ac11cd91a39af48aa17b4f63f175d3");
  errors += checkHmac< MD5  >(hex2bin("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
                              hex2bin("0102030405060708090a0b0c0d0e0f10111213141516171819"),
                              "697eaf0aca3a3aea3a75164746ffaa79");
  errors += checkHmac< SHA1 >(hex2bin("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
                              hex2bin("0102030405060708090a0b0c0d0e0f10111213141516171819"),
                              "4c9007f4026250c6bc8414f9bf50c86c2d7235da");
  // test case 5 skipped
  errors += checkHmac< MD5  >(std::string("Test Using Larger Than Block-Size Key - Hash Key First"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd");
  errors += checkHmac< SHA1 >(std::string("Test Using Larger Than Block-Size Key - Hash Key First"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "aa4ae5e15272d00e95705637ce8a3b55ed402112");
  errors += checkHmac< MD5  >(std::string("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "6f630fad67cda0ee1fb1f562db3aa53e");
  errors += checkHmac< SHA1 >(std::string("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "e8e99d0f45237d786d6bbaa7965c7808bbff1a91");

  // HMAC SHA256 test vectors from RFC4231 http://www.ietf.org/rfc/rfc4231.txt
  std::cout << "test HMAC(SHA256) ...\n";
  errors += checkHmac<SHA256>(std::string("Hi There"),
                              hex2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
                              "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
  errors += checkHmac<SHA256>(std::string("what do ya want for nothing?"),
                              std::string("Jefe"),
                              "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
  errors += checkHmac<SHA256>(hex2bin("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
  errors += checkHmac<SHA256>(hex2bin("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
                              hex2bin("0102030405060708090a0b0c0d0e0f10111213141516171819"),
                              "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b");
  // test case 5 skipped
  errors += checkHmac<SHA256>(std::string("Test Using Larger Than Block-Size Key - Hash Key First"),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
  errors += checkHmac<SHA256>(std::string("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."),
                              hex2bin("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
                              "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2");

  // summary
  if (errors == 0)
    std::cout << "all tests ok" << std::endl;
  else
    std::cerr << errors << " tests failed" << std::endl;

  return errors;
}
